package com.aube.control.mediaproxy;

import android.util.Log;

import com.huyn.baseframework.utils.Utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * Created by huyaonan on 16/7/25.
 */
public class MediaServer extends NanoHTTPD {

    public static final String TAG = "MediaServer";

    public String url;

    public String videoid = TAG;

    private OnBufferingUpdateListener onBufferingUpdateListener;

    public MediaServer(String url) {
        super();
        this.url = url;
    }

    public String getTag() {
        return videoid;
    }

    public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
        if(listener != null)
            onBufferingUpdateListener = listener;
    }

    public void setVideoId(String id) {
        videoid = id;
    }

    @Override
    public Response serve(IHTTPSession session) {
        try {
            String url = session.getUri();

            Utils.Log(videoid, "get uri..." + session.getRemoteHostName() + url);
            if (url == null) {
                Utils.Log(videoid, "url is null");
                return super.serve(session);
            }
            String range = null;
            long rangeStart = 0;

            HashMap<String, String> sendHeaders = new HashMap<>();
            Map<String, String> headers = session.getHeaders();
            for (String key : headers.keySet()) {
                Utils.Log(videoid, key + ":" + headers.get(key) + ", val:" + headers.get(key));
                if ("range".equalsIgnoreCase(key)) {
                    range = headers.get(key); // 读取range header，包含要返回的媒体流位置等信息。
                    try {
                        String rangeStr = range.substring(6, range.indexOf("-"));
                        rangeStart = Integer.parseInt(rangeStr);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    sendHeaders.put("Range", range);
                }
            }

            if(null != this.url) {
                return NanoHttpUtil.performTask(this.url, videoid, sendHeaders, this).setTag(videoid).setRange(rangeStart).setOnBufferingUpdateListener(onBufferingUpdateListener);
            } else {
                Utils.Log(videoid, "---perform request");

//            String filePath = "/sdcard/record.mp4";//getFilePath(url); // 根据url获取文件路径
                String filePath = "/sdcard/prd-06182.mp4";//getFilePath(url); // 根据url获取文件路径

                File file = new File(filePath);
                if (file != null && file.exists()) {
                    String mimeType = getMimeType(filePath); //根据文件名返回mimeType:image/jpg,video/mp4,etc

                    Response res = null;
                    if (range == null) {
                        // 如果range为空，返回该文件的所有媒体流
                        InputStream is = new FileInputStream(file);
                        res = new Response(Status.OK, mimeType, is, file.length());
                        res.addHeader("Content-Length", String.valueOf(file.length()));
                    } else {
                        // 根据range参数，返回制定位置的媒体流
                        res = getPartialResponse(file, range, mimeType);
                    }

                    Calendar cd = Calendar.getInstance();
                    cd.setTimeZone(TimeZone.getTimeZone("GMT"));
                    cd.setTimeInMillis(file.lastModified());
                    res.addHeader("Last-Modified", getGMTTimeFormat(file));

                    return res;
                } else {
                    Log.e(TAG, "file is null");
                }

                return super.serve(session);
            }
        } catch (Exception e) {
            Log.e(TAG, "HttpServer serve:", e);
            e.printStackTrace();
        } finally {
            Log.e(TAG, "before return in serve");
        }
        return super.serve(session);
    }

    private String getMimeType(String path) {
        return "video/mp4";
    }

    /**
     * HttpServletResponse中date的设置
     * 例如:Wed, 23 Mar 2016 06:56:53 GMT
     * @param file
     * @return
     */
    private String getGMTTimeFormat(File file) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
        cal.setTimeInMillis(file.lastModified());
        SimpleDateFormat sd = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.CHINA);
        sd.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sd.format(cal.getTime());
    }

    // 根据range中定义的范围返回媒体流
    private Response getPartialResponse(File file, String rangeHeader, String mimeType) throws IOException {
        String rangeValue = rangeHeader.trim().substring("bytes=".length());
        long fileLength = file.length();
        long start, end;
        if (rangeValue.startsWith("-")) {
            end = fileLength - 1;
            start = fileLength - 1 - Long.parseLong(rangeValue.substring("-".length()));
        } else {
            String[] range = rangeValue.split("-");
            start = Long.parseLong(range[0]);
            end = range.length > 1 ? Long.parseLong(range[1]) : fileLength - 1;
        }
        if (end > fileLength - 1) {
            end = fileLength - 1;
        }
        // 解析range中的start，end位置
        InputStream fileInputStream;
        if (start <= end) {
            long contentLength = end - start + 1;
            fileInputStream = new FileInputStream(file);
            fileInputStream.skip(start); //将媒体流跳转到start处，然后返回

            Response response = new Response(Status.PARTIAL_CONTENT, mimeType, fileInputStream, fileLength);
            response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);
            response.addHeader("Content-Length", contentLength + "");
            return response;
        } else {
            return newFixedLengthResponse(Status.RANGE_NOT_SATISFIABLE, MIME_HTML, rangeHeader);
        }
    }

    @Override
    public void stop() {
        super.stop();
        onBufferingUpdateListener = null;
    }

}
